package com.aplink.generic.webservice;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;

import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.json.JSONException;
import org.json.JSONObject;

import android.net.Uri;
import android.text.TextUtils;

import com.aplink.generic.constant.WebServiceContant;
import com.aplink.generic.network.GenericFile;
import com.aplink.generic.pojo.ContentData;
import com.aplink.generic.pojo.GenericObject;
import com.aplink.generic.pojo.ObjPropInfo;
import com.aplink.generic.sharepreference.GenericSharePreference;
import com.aplink.generic.util.LogUtil;

public class HttpURL {
    private static final String ACTION = "action";
    private static final String ALLOW_CHARACTER_URL = "@#&=*+-_.,:!?()/~'%";
    private static final String JSON_ACTION = "jsonAction";
    private static final String JSON_CONDITION = "jsonCondition";
    private static final String JSON_EMAIL = "email";
    private static final String JSON_TABLE = "table";
    private static final String JSON_TOKEN = "token";
    private static final String JSON_VALUE = "jsonValue";
    private boolean hasDownloadFile;
    private String mDomain;
    private String mEmail;
    private ObjPropInfo mFileObjPropInfo;
    private GenericObject mGenericEmail;
    private GenericObject mGenericObject;
    private String mJsonAction;
    private String mJsonCondition;
    private String mJsonValue;
    private ArrayList<GenericFile> mListDeleteFiles;
    private ArrayList<GenericFile> mListUploadFiles;
    private int mMethod = WebServiceContant.GET;
    private ContentData mObjPropCol;
    private String mTable;
    private String mToken;
    private String mWebserviceFunction;

    public HttpURL() {
        this.mListUploadFiles = new ArrayList<GenericFile>();
        this.mListDeleteFiles = new ArrayList<GenericFile>();
        this.mToken = GenericSharePreference.getInstance().getToken();
    }

    public HttpURL(final String jsonValue, final String jsonCondition,
            final String action, final String table, final String domain,
            final String webserviceFunction,
            final ArrayList<GenericFile> listFiles) {
        this.mToken = GenericSharePreference.getInstance().getToken();
        this.mJsonValue = jsonValue;
        this.mJsonCondition = jsonCondition;
        this.mJsonAction = action;
        this.mTable = table;
        this.mDomain = domain;
        this.mWebserviceFunction = webserviceFunction;
        setListUploadFiles(listFiles);
        this.mListUploadFiles = new ArrayList<GenericFile>();
        this.mListDeleteFiles = new ArrayList<GenericFile>();
    }

    public String getAction() {
        return this.mJsonAction;
    }

    public ContentData getContentData() {
        return this.mObjPropCol;
    }

    public String getDomain() {
        return this.mDomain;
    }

    public ObjPropInfo getFileObjPropInfo() {
        return this.mFileObjPropInfo;
    }

    public GenericObject getGenericObject() {
        return this.mGenericObject;
    }

    public HttpEntity getHttpEntity() {
        if (this.mMethod == WebServiceContant.POST) {
            this.mJsonValue = parseJsonValue(this.mObjPropCol,
                    this.mGenericObject);
            final MultipartEntityBuilder builder = MultipartEntityBuilder
                    .create()
                    .addPart("token",
                            new StringBody(this.mToken, ContentType.TEXT_PLAIN))
                    .addPart(
                            "action",
                            new StringBody(this.mJsonAction,
                                    ContentType.TEXT_PLAIN))
                    .addPart(
                            "jsonValue",
                            new StringBody(this.mJsonValue,
                                    ContentType.TEXT_PLAIN))
                    .addPart("table",
                            new StringBody(this.mTable, ContentType.TEXT_PLAIN));
            if (this.mJsonCondition != null) {
                try {
                    final JSONObject jsonObject = new JSONObject();
                    jsonObject.put("CreatedTime", this.mJsonCondition);
                    builder.addPart("jsonCondition",
                            new StringBody(jsonObject.toString(),
                                    ContentType.TEXT_PLAIN));
                } catch (final JSONException e) {
                    e.printStackTrace();
                }
            } else {
                builder.addPart("jsonCondition", new StringBody("{}",
                        ContentType.TEXT_PLAIN));
            }
            if (!this.mListUploadFiles.isEmpty()) {
                for (final GenericFile fileUrl : this.mListUploadFiles) {
                    builder.addPart("image",
                            new FileBody(new File(fileUrl.getLocalPath())));
                }
            }

            final StringBuilder listDelete = new StringBuilder();
            for (int i = 0; i < this.mListDeleteFiles.size(); i++) {
                final GenericFile genericFile = this.mListDeleteFiles.get(i);
                final String fileName = genericFile.getName();
                listDelete.append(fileName);
                if (i < (this.mListDeleteFiles.size() - 1)) {
                    listDelete.append(",");
                }
            }
            if (this.mJsonAction.equalsIgnoreCase("update")) {
                builder.addPart("imageDeleteList",
                        new StringBody(listDelete.toString(),
                                ContentType.TEXT_PLAIN));
            }
            return builder.build();
        }
        return null;
    }

    public String getJsonCondition() {
        return this.mJsonCondition;
    }

    public String getJsonValue() {
        return this.mJsonValue;
    }

    public ArrayList<GenericFile> getListDeleteFiles() {
        return this.mListDeleteFiles;
    }

    public ArrayList<GenericFile> getListFiles() {
        return this.mListUploadFiles;
    }

    public int getMethod() {
        return this.mMethod;
    }

    public String getToken() {
        return this.mToken;
    }

    private String getURL() {
        final StringBuilder url = new StringBuilder();
        url.append(this.mDomain).append(this.mWebserviceFunction);
        if (this.mMethod == WebServiceContant.GET) {
            try {
                // Append json action.
                JSONObject jsonObject = new JSONObject();
                if (this.mJsonAction == null) {
                    url.append(String.format("%s={}", HttpURL.JSON_ACTION))
                            .append("&");
                } else {
                    jsonObject.put(HttpURL.ACTION, this.mJsonAction);
                    url.append(
                            String.format("%s=%s", HttpURL.JSON_ACTION,
                                    jsonObject.toString())).append("&");
                }
                // Append json table.
                jsonObject = new JSONObject();
                if (this.mTable == null) {
                    url.append(String.format("%s={}", HttpURL.JSON_TABLE))
                            .append("&");
                } else {
                    jsonObject.put(HttpURL.JSON_TABLE, this.mTable);
                    url.append(
                            String.format("%s=%s", HttpURL.JSON_TABLE,
                                    jsonObject.toString())).append("&");
                }
                // Append json condition.
                jsonObject = new JSONObject();
                if (this.mJsonCondition == null) {
                    url.append(String.format("%s={}", HttpURL.JSON_CONDITION))
                            .append("&");
                } else {
                    jsonObject.put("CreatedTime", this.mJsonCondition);
                    url.append(
                            String.format("%s=%s", HttpURL.JSON_CONDITION,
                                    jsonObject.toString())).append("&");
                }

                // Append json token.
                jsonObject = new JSONObject();
                if (this.mToken == null) {
                    url.append(String.format("%s={}", HttpURL.JSON_TOKEN))
                            .append("&");
                } else {
                    jsonObject.put(HttpURL.JSON_TOKEN, this.mToken);
                    url.append(
                            String.format("%s=%s", HttpURL.JSON_TOKEN,
                                    jsonObject.toString())).append("&");
                }

                // Append json value.
                this.mJsonValue = parseJsonValue(this.mObjPropCol,
                        this.mGenericObject);
                if (this.mJsonValue == null) {
                    url.append(String.format("%s={}", HttpURL.JSON_VALUE))
                            .append("&");
                } else {
                    url.append(
                            String.format("%s=%s", HttpURL.JSON_VALUE,
                                    this.mJsonValue)).append("&");
                }

                this.mEmail = parseJsonValue(this.mObjPropCol,
                        this.mGenericEmail);
                if (this.mEmail == null) {
                    url.append(String.format("%s={}", HttpURL.JSON_EMAIL));
                } else {
                    url.append(String.format("%s=%s", HttpURL.JSON_EMAIL,
                            this.mEmail));
                }
                return url.toString();
            } catch (final JSONException e) {
                e.printStackTrace();
            }
        }
        return url.toString();
    }

    public String getWebserviceFunction() {
        return this.mWebserviceFunction;
    }

    public String getWebserviceURL() {
        if (this.mMethod == WebServiceContant.GET) {
            return Uri.encode(getURL(), HttpURL.ALLOW_CHARACTER_URL);
        }
        return getURL();
    }

    public String initTableName() {
        return this.mTable;
    }

    public boolean isHasDownloadFile() {
        return this.hasDownloadFile;
    }

    @SuppressWarnings("unchecked")
    private String parseJsonValue(final ContentData objPropCol,
            final GenericObject genericObject) {
        if ((objPropCol == null) || (genericObject == null)) {
            return null;
        }
        final StringBuilder jsonValue = new StringBuilder();
        try {
            for (int i = 0; i < objPropCol.getWebServiceParameters().size(); i++) {
                final JSONObject jsonObject = objPropCol
                        .getWebServiceParameters().valueAt(i);
                final JSONObject finalResult = new JSONObject();
                final Iterator<String> iter = jsonObject.keys();
                while (iter.hasNext()) {
                    final String keyJson = iter.next();
                    final String key = jsonObject.getString(keyJson);
                    String value = genericObject.get(keyJson).getValue();
                    if (TextUtils.isEmpty(value)) {
                        final ObjPropInfo propInfo = objPropCol.get(keyJson);
                        if ((propInfo != null) && propInfo.isFKey()) {
                            value = genericObject.get(
                                    propInfo.getForeignFullColumnName())
                                    .getValue();
                            if (!TextUtils.isEmpty(value)) {
                                finalResult.put(keyJson, value);
                            }
                        }
                    } else {
                        finalResult.put(key, value);
                    }
                }
                jsonValue.append(finalResult.toString());
            }
        } catch (final JSONException e) {
            e.printStackTrace();
        }
        LogUtil.info("APLINK_JSON_VALUE", jsonValue.toString(),
                "parseJsonValue", getClass());
        return jsonValue.toString();
    }

    public HttpURL setAction(final String action) {
        this.mJsonAction = action;
        return this;
    }

    public HttpURL setDomain(final String domain) {
        this.mDomain = domain;
        return this;
    }

    public HttpURL setEmail(final GenericObject genericObject) {
        this.mGenericEmail = genericObject;
        return this;
    }

    public void setFileObjPropInfo(final ObjPropInfo fileObjPropInfo) {
        this.mFileObjPropInfo = fileObjPropInfo;
    }

    public void setGenericObject(final GenericObject genericObject) {
        this.mGenericObject = genericObject;
    }

    public void setHasDownloadFile(final boolean hasDownloadFile) {
        this.hasDownloadFile = hasDownloadFile;
    }

    public HttpURL setJsonCondition(final String jsonCondition) {
        this.mJsonCondition = jsonCondition;
        return this;
    }

    public HttpURL setJsonValue(final GenericObject genericObject) {
        this.mGenericObject = genericObject;
        return this;
    }

    public HttpURL setListDeleteFiles(
            final ArrayList<GenericFile> listDeleteFiles) {
        this.mListDeleteFiles = listDeleteFiles;
        return this;
    }

    public HttpURL setListUploadFiles(final ArrayList<GenericFile> listFiles) {
        this.mListUploadFiles = listFiles;
        return this;
    }

    public HttpURL setMethod(final int method) {
        this.mMethod = method;
        return this;
    }

    public HttpURL setObjPropCol(final ContentData objPropCol) {
        this.mObjPropCol = objPropCol;
        return this;
    }

    public HttpURL setTable(final String table) {
        this.mTable = table;
        return this;
    }

    public HttpURL setToken(final String token) {
        this.mToken = token;
        return this;
    }

    public HttpURL setWebserviceFunction(final String webserviceFunction) {
        this.mWebserviceFunction = webserviceFunction;
        return this;
    }

    @Override
    public String toString() {
        return getURL();
    }
}
